/**
 * StreamProcessor - 流式处理器
 * 基于 Augment Code 的流式响应处理机制
 */

import { EventEmitter } from 'events';
import { 
  StreamEvent, 
  NodeType, 
  StructuredNode, 
  ConversationContext 
} from './types';

export interface StreamProcessorConfig {
  bufferSize?: number;
  flushInterval?: number;
  enableBuffering?: boolean;
}

export class StreamProcessor extends EventEmitter {
  private buffer: string = '';
  private nodeBuffer: StructuredNode[] = [];
  private config: StreamProcessorConfig;
  private flushTimer: NodeJS.Timeout | null = null;
  private isProcessing = false;

  constructor(config: StreamProcessorConfig = {}) {
    super();
    this.config = {
      bufferSize: 1024,
      flushInterval: 100,
      enableBuffering: true,
      ...config
    };
  }

  /**
   * 处理流式事件
   */
  async processStreamEvent(event: StreamEvent, context?: ConversationContext): Promise<void> {
    this.emit('eventReceived', event);

    switch (event.type) {
      case 'start':
        await this.handleStreamStart(event);
        break;
      
      case 'chunk':
        await this.handleTextChunk(event);
        break;
      
      case 'node':
        await this.handleStructuredNode(event);
        break;
      
      case 'tool':
        await this.handleToolEvent(event);
        break;
      
      case 'end':
        await this.handleStreamEnd(event);
        break;
      
      case 'error':
        await this.handleStreamError(event);
        break;
    }
  }

  /**
   * 处理流开始事件
   */
  private async handleStreamStart(event: StreamEvent): Promise<void> {
    this.buffer = '';
    this.nodeBuffer = [];
    this.isProcessing = true;
    
    this.emit('streamStarted', event);
  }

  /**
   * 处理文本块
   */
  private async handleTextChunk(event: StreamEvent): Promise<void> {
    const text = event.data.text || '';
    
    if (this.config.enableBuffering) {
      this.buffer += text;
      
      // 检查是否需要刷新缓冲区
      if (this.buffer.length >= (this.config.bufferSize || 1024)) {
        await this.flushTextBuffer();
      } else {
        this.scheduleFlush();
      }
    } else {
      // 直接发送文本块
      this.emit('textChunk', { text, timestamp: event.timestamp });
    }
  }

  /**
   * 处理结构化节点
   */
  private async handleStructuredNode(event: StreamEvent): Promise<void> {
    if (!event.nodeType || !event.data) {
      return;
    }

    const node = this.createStructuredNode(event.nodeType, event.data, event.timestamp);
    
    if (this.config.enableBuffering) {
      this.nodeBuffer.push(node);
      
      // 某些节点类型需要立即处理
      if (this.shouldFlushImmediately(event.nodeType)) {
        await this.flushNodeBuffer();
      }
    } else {
      this.emit('structuredNode', node);
    }
  }

  /**
   * 处理工具事件
   */
  private async handleToolEvent(event: StreamEvent): Promise<void> {
    this.emit('toolEvent', event.data);
  }

  /**
   * 处理流结束事件
   */
  private async handleStreamEnd(event: StreamEvent): Promise<void> {
    // 刷新所有缓冲区
    await this.flushAllBuffers();
    
    this.isProcessing = false;
    this.emit('streamCompleted', event);
  }

  /**
   * 处理流错误事件
   */
  private async handleStreamError(event: StreamEvent): Promise<void> {
    // 刷新所有缓冲区
    await this.flushAllBuffers();
    
    this.isProcessing = false;
    this.emit('streamError', event.data);
  }

  /**
   * 刷新文本缓冲区
   */
  private async flushTextBuffer(): Promise<void> {
    if (this.buffer.length > 0) {
      this.emit('textChunk', { 
        text: this.buffer, 
        timestamp: Date.now() 
      });
      this.buffer = '';
    }
  }

  /**
   * 刷新节点缓冲区
   */
  private async flushNodeBuffer(): Promise<void> {
    if (this.nodeBuffer.length > 0) {
      for (const node of this.nodeBuffer) {
        this.emit('structuredNode', node);
      }
      this.nodeBuffer = [];
    }
  }

  /**
   * 刷新所有缓冲区
   */
  private async flushAllBuffers(): Promise<void> {
    await this.flushTextBuffer();
    await this.flushNodeBuffer();
    
    if (this.flushTimer) {
      clearTimeout(this.flushTimer);
      this.flushTimer = null;
    }
  }

  /**
   * 调度刷新
   */
  private scheduleFlush(): void {
    if (this.flushTimer) {
      return;
    }

    this.flushTimer = setTimeout(async () => {
      await this.flushTextBuffer();
      this.flushTimer = null;
    }, this.config.flushInterval || 100);
  }

  /**
   * 检查是否应该立即刷新
   */
  private shouldFlushImmediately(nodeType: NodeType): boolean {
    return [
      NodeType.MainTextFinished,
      NodeType.ToolUseStart,
      NodeType.ToolUse,
      NodeType.SuggestedQuestions
    ].includes(nodeType);
  }

  /**
   * 创建结构化节点
   */
  private createStructuredNode(
    nodeType: NodeType,
    data: any,
    timestamp: number
  ): StructuredNode {
    const baseNode = {
      type: nodeType,
      ts: timestamp,
      requestId: data.requestId || ''
    };

    switch (nodeType) {
      case NodeType.RawResponse:
        return { ...baseNode, text: data.text || '' } as any;
      
      case NodeType.SuggestedQuestions:
        return { ...baseNode, questions: data.questions || [] } as any;
      
      case NodeType.ToolUse:
        return { 
          ...baseNode, 
          tool: data.tool,
          input: data.input,
          result: data.result,
          error: data.error
        } as any;
      
      case NodeType.ToolUseStart:
        return {
          ...baseNode,
          tool: data.tool,
          input: data.input
        } as any;
      
      case NodeType.AgentMemory:
        return {
          ...baseNode,
          memoryId: data.memoryId,
          content: data.content
        } as any;
      
      case NodeType.Thinking:
        return { ...baseNode, text: data.text } as any;
      
      case NodeType.MainTextFinished:
        return baseNode as any;
      
      default:
        return baseNode as any;
    }
  }

  /**
   * 获取处理状态
   */
  getStatus() {
    return {
      isProcessing: this.isProcessing,
      bufferSize: this.buffer.length,
      nodeBufferSize: this.nodeBuffer.length,
      hasScheduledFlush: this.flushTimer !== null
    };
  }

  /**
   * 更新配置
   */
  updateConfig(config: Partial<StreamProcessorConfig>): void {
    this.config = { ...this.config, ...config };
  }

  /**
   * 重置处理器
   */
  reset(): void {
    this.buffer = '';
    this.nodeBuffer = [];
    this.isProcessing = false;
    
    if (this.flushTimer) {
      clearTimeout(this.flushTimer);
      this.flushTimer = null;
    }
  }

  /**
   * 清理资源
   */
  dispose(): void {
    this.reset();
    this.removeAllListeners();
  }
}
